import {
  _decorator,
  AudioClip,
  Component,
  EventTouch,
  instantiate,
  Node,
  Prefab,
  UITransform,
  Vec2,
  Vec3,
} from "cc";
import { BaseSceneManager } from "../base-scene-manager";
import { DataManager } from "../../runtime/data-manager";
import { BallManager } from "./ball-manager";
import { SceneType } from "../../model";
const { ccclass, property } = _decorator;

const CIRCLE_RADIUS = 80;

@ccclass("H2aSceneManager")
export class H2aSceneManager extends BaseSceneManager {
  @property([Node])
  circles: Node[] = [];

  @property(Prefab)
  linePreb: Prefab = null;

  @property(Node)
  lineContainer: Node = null;

  @property(Node)
  ballContainer: Node = null;

  @property([Prefab])
  ballPrefabs: Prefab[] = [];

  private preBgm: AudioClip = null;

  private readonly circleMap: Map<number, number[]> = new Map([
    [1, [3, 4, 7]],
    [2, [3, 4]],
    [3, [2, 4, 5]],
    [4, [1, 2, 3, 5, 6, 7]],
    [5, [3, 4, 6, 7]],
    [6, [4, 5]],
    [7, [1, 4, 5]],
  ]);

  start() {
    this.preBgm = DataManager.Instance.getCurAudioClip();
    if (this.bgm) {
      DataManager.Instance.playAudio(this.bgm);
    }

    super.start();

    this.generateMap();
  }

  render() {
    if (DataManager.Instance.h2aResoleved) {
      this.changeScene(undefined, SceneType.H2);
      return;
    }

    this.ballContainer.removeAllChildren();

    const correctAnswer = DataManager.Instance.Correct_Answer;
    DataManager.Instance.curAnwer.forEach((ballNo, circleIndex) => {
      if (ballNo !== null) {
        const isInCorrectPos = ballNo === correctAnswer[circleIndex];
        const ballNode = instantiate(this.ballPrefabs[ballNo - 1]);
        this.ballContainer.addChild(ballNode);
        ballNode.setPosition(this.circles[circleIndex].position);
        ballNode.getComponent(BallManager).render(isInCorrectPos);
      }
    });
  }

  generateMap() {
    for (const [
      startIndex,
      reachableCircleIndexs,
    ] of this.circleMap.entries()) {
      reachableCircleIndexs.forEach((reachableCircleIndex) => {
        if (startIndex < reachableCircleIndex) {
          const pos1 = this.circles[startIndex - 1].position;
          const pos2 = this.circles[reachableCircleIndex - 1].position;

          this.generateLine(pos1, pos2);
        }
      });
    }
  }

  generateLine(pos1: Vec3, pos2: Vec3) {
    const lineLength =
      Math.sqrt(Math.pow(pos1.x - pos2.x, 2) + Math.pow(pos1.y - pos2.y, 2)) -
      2 * CIRCLE_RADIUS;

    const linePos = new Vec3((pos2.x + pos1.x) / 2, (pos2.y + pos1.y) / 2, 0);

    const angle = Math.atan2(pos2.y - pos1.y, pos2.x - pos1.x);
    const rotatedAngle = (angle / Math.PI) * 180;

    const line = instantiate(this.linePreb);
    this.lineContainer.addChild(line);
    line.setPosition(linePos);
    line.setRotationFromEuler(0, 0, rotatedAngle);
    const lineUITransform = line.getComponent(UITransform);
    lineUITransform.setContentSize(
      lineLength,
      lineUITransform.contentSize.height
    );
  }

  onCircleTouch(event: EventTouch, circleNoStr: string) {
    const circleNo = parseInt(circleNoStr);
    const circleIndex = circleNo - 1;
    const curAnwer = DataManager.Instance.curAnwer;
    if (curAnwer[circleIndex] === null) {
      return;
    }

    const reachableCircleNos = this.circleMap.get(circleNo);
    const targetCircleNo = reachableCircleNos.find(
      (circleNo) => curAnwer[circleNo - 1] === null
    );
    if (targetCircleNo === undefined) {
      return;
    }

    curAnwer[targetCircleNo - 1] = curAnwer[circleIndex];
    curAnwer[circleIndex] = null;
    DataManager.Instance.updateAnser(curAnwer);
  }

  resetAnswer() {
    DataManager.Instance.resetAnser();
  }

  protected onDestroy() {
    DataManager.Instance.playAudio(this.preBgm);
    super.onDestroy();
  }
}
